package per.hnvcam.searchext.controller.administration;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;

import org.apache.commons.lang.ArrayUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;

import per.hnvcam.common.OrderedSet;
import per.hnvcam.common.impl.OrderedSetImpl;
import per.hnvcam.hedge.algebra.Hedge2AlgebraDefinition;
import per.hnvcam.hedge.algebra.Hedge2Quantifier;
import per.hnvcam.searchext.services.TrainingService;
import per.hnvcam.searchext.services.ForecastService;
import per.hnvcam.searchext.services.RuleService;
import per.hnvcam.searchext.services.SpecialQuery;
import per.hnvcam.searchext.data.dao.WebReferenceDAO;
import per.hnvcam.searchext.data.dao.WordCountDAO;
import per.hnvcam.searchext.data.dao.WordDAO;
import per.hnvcam.searchext.data.model.SystemConfiguration;
import per.hnvcam.searchext.data.model.WebReference;
import per.hnvcam.searchext.data.model.Word;
import per.hnvcam.searchext.data.model.WordCount;

@Controller("GeneralController")
public class GeneralController {

   private static final String ADMIN_HOME_PAGE = "administration/home";
   private static final String ADMIN_SYSTEM_PAGE = "administration/system";
   private static final String PAGE_DETAILS_PAGE = "administration/page";
   private static final String ADMIN_WORDS_PAGE = "administration/words";

   @Autowired
   @Qualifier("WebReferenceDAO")
   private WebReferenceDAO webReferenceDAO;

   @Autowired
   @Qualifier("WordCountDAO")
   private WordCountDAO wordCountDAO;

   @Autowired
   @Qualifier("WordDAO")
   private WordDAO wordDAO;

   @Autowired
   @Qualifier("SpecialQuery")
   private SpecialQuery specialQuery;

   @Autowired
   @Qualifier("ForecastService")
   private ForecastService forecastService;

   @Autowired
   @Qualifier("RuleService")
   private RuleService ruleService;

   @Autowired
   @Qualifier("TrainingService")
   private TrainingService trainingService;

   @Autowired
   @Qualifier("Hedge2AlgebraDefinition")
   private Hedge2AlgebraDefinition hedgeAlgebraDefinition;

   @Autowired
   @Qualifier("Hedge2Quantifier")
   private Hedge2Quantifier fuzzyQuantifier;

   @RequestMapping(value = "/administration/home.jhtml", method = RequestMethod.GET)
   public String showAdminHome(HttpServletRequest request, Model model) {
      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("classifiedClasses", systemConfiguration.getClasses());
      model.addAttribute("pageList", webReferenceDAO.listPages());
      model.addAttribute("newPage", new WebReference());
      return ADMIN_HOME_PAGE;
   }

   @RequestMapping(value = "/administration/home.jhtml", method = RequestMethod.POST)
   public String addNewPage(HttpServletRequest request, @ModelAttribute("newPage") WebReference webReference, Model model) {
      String status;
      try {
         webReferenceDAO.savePage(webReference);
         status = "Page was added successfully.";
      }
      catch (Exception e) {
         e.printStackTrace();
         status = "Could not add new page: " + e.getMessage();
      }

      try {
         trainingService.trainFromWebReference(webReference);
      }
      catch (Exception e) {
         e.printStackTrace();
         status = "Could not train from page";
      }

      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("classifiedClasses", systemConfiguration.getClasses());
      model.addAttribute("pageList", webReferenceDAO.listPages());
      model.addAttribute("status", status);
      return ADMIN_HOME_PAGE;
   }

   @RequestMapping(value = "/administration/system.jhtml", method = RequestMethod.GET)
   public String showSystemConfiguration(HttpServletRequest request, Model model) {
      SystemConfiguration systemConfiguration = specialQuery.getSystemConfiguration();
      model.addAttribute("initialRuleSetSize",
            forecastService.determineInitialRulesSetSize(systemConfiguration.getRuleLengthMinimum(),
                  systemConfiguration.getRuleLengthMaximum(), ruleService.getAllBaseRulesData()));
      model.addAttribute("systemConfiguration", systemConfiguration);
      return ADMIN_SYSTEM_PAGE;
   }

   @RequestMapping(value = "/administration/system.jhtml", method = RequestMethod.POST)
   public String saveSystemConfiguration(HttpServletRequest request, @ModelAttribute("systemConfiguration") SystemConfiguration systemConfiguration,
                                Model model) {
      model.addAttribute("status", specialQuery.saveSystemConfiguration(systemConfiguration));
      model.addAttribute("initialRuleSetSize",
            forecastService.determineInitialRulesSetSize(systemConfiguration.getRuleLengthMinimum(),
                  systemConfiguration.getRuleLengthMaximum(), ruleService.getAllBaseRulesData()));
      return ADMIN_SYSTEM_PAGE;
   }



   @RequestMapping(value = "/administration/page.jhtml", method = RequestMethod.GET)
   public String showPageDetails(HttpServletRequest request, @RequestParam("pageId") long pageId, Model model) {
      WebReference pageDetails = webReferenceDAO.findById(pageId);
      List<WordCount> wordCounts = wordCountDAO.findByWebReferenceId(pageId);
      model.addAttribute("pageDetails", pageDetails);
      model.addAttribute("wordCounts", wordCounts);
      return PAGE_DETAILS_PAGE;
   }

   @RequestMapping(value = "/administration/wordsSummary.jhtml", method = RequestMethod.GET)
   public String showWordsInformation(@RequestParam(value = "operation", required = false) String operation,
                                      @RequestParam(value = "page", required = false) String page, Model model) {
      if (operation != null && operation.equals("fuzzy")) {
         trainingService.determineWordAmount();
      }

      int currentPage = 1;

      if (page != null) {
         currentPage = Integer.parseInt(page);
      }

      List<Word> wordList = wordDAO.listWords();
      List<Word> actualList = new ArrayList<Word>();

      int start = (currentPage - 1) * 100;
      int end = currentPage * 100;
      int maxPage = (int) (Math.floor(wordList.size() / 100) + 1);

      for (int i = start; i < end; i++) {
         actualList.add(wordList.get(i));
      }

      Map<Long, Map<Long, WordCount>> wordMap = specialQuery.getWordSummaryOf(actualList);

      List<WebReference> webReferenceList = webReferenceDAO.listPages();

      model.addAttribute("wordList", actualList);
      model.addAttribute("wordMap", wordMap);
      model.addAttribute("pages", webReferenceList);
      model.addAttribute("currentPage", currentPage);
      model.addAttribute("previousPage", currentPage > 1 ? currentPage - 1 : null);
      model.addAttribute("nextPage", currentPage < maxPage ? currentPage + 1 : null);
      return ADMIN_WORDS_PAGE;
   }

}
